home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / MenuScripter / Sources / MSScript.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-25  |  35.9 KB  |  1,343 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSScript.c
  3.     
  4.     Version 1.0d6
  5.     
  6.     Copyright © SRL Data 1992, 1993
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : SRL Data
  11.     Originally Developed for UK.DTS
  12.     
  13.     Contains OSA interface of MenuScripter.
  14.  
  15.     Change History :
  16.  
  17.       9-Jul-92 : NH : File created
  18.      12-Aug-92 : NH : Added checks for InitEditor
  19.      
  20.     Changes for 1.0d3:
  21.     
  22.         27-Aug-92 : NH : ExecuteScriptForMenu returns error code
  23.         
  24.     Changes for 1.0d4:
  25.         
  26.         14-Nov-92 : NH : Gustav now system Extension so don't try to launch it!
  27.                                          Remove editing from menu item
  28. */
  29.  
  30. #include <Memory.h>
  31. #include <Resources.h>
  32. #include <TextEdit.h>
  33. #include <Controls.h>
  34. #include <Dialogs.h>
  35. #include <Errors.h>
  36. #include <Files.h>
  37. #include <Folders.h>
  38. #include <Components.h>
  39. #include <AppleEvents.h>
  40. #include <OSA.h>
  41. #include <AppleScript.h>
  42. #include <AERegistry.h>
  43. #include <Processes.h>
  44.  
  45. #include "MSGlobals.h"
  46. #include "MSUtils.h"
  47. #include "MSAEUtils.h"
  48. #include "MSWindow.h"
  49.  
  50. /*
  51.     Each menu (or menu item) can have a script associated with it. This
  52.     script has an ID equal to 32 * theMenuID + theItem number. A script
  53.     with an item number of 0 applies to the whole menu unless it is 
  54.     overridden by a particular script for an item in the menu.
  55.     
  56.     Scripts are stored in two resource types
  57.         'scpt' is a compiled script as returned by OSAStore()
  58.         'SCPT' is a raw text script as defined in the resource file
  59.         
  60.     At open application time scripts are built from the 'SCPT' resources 
  61.     if there are not any existing complied scripts of that resource ID.
  62.     These are stored in the preferences file for the application.
  63.     
  64.     One problem with the scripted menu commands is that if the application
  65.     name is changed the target is no longer found. This may be addressed later.
  66.  
  67.     In order to execute the scripts the application needs to connect to the
  68.     AppleScript component (called Gustav in the Alpha release). The search
  69.     of the available volumes uses the desktop database. Hence the search is
  70.     limited to hard disks.
  71.     
  72. */
  73.  
  74. #define kMaxScriptsInApp 100
  75. #define kCompiledScriptType kOSAScriptResourceType
  76. #define kTextScriptType 'SCPT'
  77.  
  78. struct MyScriptRecord {
  79.   OSAID  theScriptID;
  80.     short  theResID;
  81. };
  82.  
  83. typedef struct MyScriptRecord MyScriptRecord;
  84.  
  85. ComponentInstance gScriptingComponent;
  86. short             gActiveMenuItem;
  87. OSASendUPP             oldSendProc;
  88. long              refCon;
  89. MyScriptRecord   *menuScripts;
  90. short             gNumScripts;
  91. short             gPrefsRefFile;
  92.  
  93. /*
  94.     These are used in documentation but not defined in the interfaces
  95. */
  96.  
  97. #ifndef kComponentNotFound
  98. #define kComponentNotFound -1
  99. #endif
  100.  
  101. #define kAEDontRecord 0x00001000
  102.  
  103. pascal OSErr MySendProc(const AppleEvent*        theAppleEvent,
  104.                                                 AppleEvent*                    reply,
  105.                                                 AESendMode                     sendMode,
  106.                                                 AESendPriority             sendPriority,
  107.                                                 long                           timeOutInTicks,
  108.                                                 AEIdleUPP                      idleProc,
  109.                                                 AEFilterUPP                  filterProc,
  110.                                                 long                           refCon)
  111.     { 
  112. #pragma unused(refCon)
  113.         DescType     typeCode;
  114.         Size         descSize;
  115.         OSErr        myErr;
  116.         OSErr        ignoreErr;
  117.         OSType       whatEvent;
  118.         AppleEvent   myCopyAEvt;
  119.         
  120.         myErr = AEDuplicateDesc(theAppleEvent, &myCopyAEvt);
  121.     
  122.         myErr = AEGetAttributePtr(&myCopyAEvt,
  123.                                                             keyEventIDAttr,
  124.                                                             typeType,
  125.                                                             &typeCode,
  126.                                                             (Ptr) &whatEvent,
  127.                                                             sizeof(whatEvent),
  128.                                                             &descSize);
  129.                                                             
  130.         ignoreErr = AEDisposeDesc(&myCopyAEvt);
  131.         
  132.         if (myErr != noErr) whatEvent = 0x3F3F3F3F;
  133.         
  134.         /*
  135.             Record the final Set Data that occurs due to a script
  136.             'gdte' = id sent to get 'aete' resource from app, dealt with
  137.             by system handler.
  138.         */
  139.       if ((sendMode & kAEDontRecord) && 
  140.                 ((whatEvent!=kAEGetData) && (whatEvent!='gdte')))
  141.           sendMode = sendMode - kAEDontRecord;
  142.             
  143.         /* will be this when a5 bug fixed
  144.         return((*oldSendProc)(theAppleEvent,
  145.                                      reply,
  146.                                      sendMode,
  147.                                      sendPriority,
  148.                                      timeOutInTicks,
  149.                                      idleProc,
  150.                                      filterProc,
  151.                                      refCon));
  152.         */
  153.         
  154.         return(AESend(theAppleEvent,
  155.                       reply,
  156.                                     sendMode,
  157.                                     sendPriority,
  158.                                     timeOutInTicks,
  159.                                     idleProc,
  160.                                     filterProc));                            
  161.     }    /* MySendProc */
  162.     
  163. pascal OSAID GetScriptIDForResID(short lookForID)
  164.     {
  165.         short ctr;
  166.         
  167.         for (ctr=0; ctr<gNumScripts; ctr++)
  168.             {
  169.                 if (menuScripts[ctr].theResID==lookForID)
  170.                     return(menuScripts[ctr].theScriptID);
  171.             }
  172.             
  173.         return(kOSANullScript);
  174.     }
  175.     
  176. /*
  177.     Name : GetOpenPreferencesResourceFile
  178.     Purpose : Opens the prefs file, in the system prefs folder
  179.               creating it if it is not found. Sets the current
  180.                         resource file to the prefs file so that resources
  181.                         will be read from there in preference to the app
  182.                         if they have been overridden, and new resources
  183.                         will be created in it.
  184. */
  185.     
  186. pascal OSErr GetOpenPreferencesResourceFile(short *theRefNum)
  187.     {
  188.       short  foundVRefNum;
  189.         long   foundDirID;
  190.         OSErr  myErr;
  191.         
  192.         myErr = FindFolder(kOnSystemDisk,
  193.                            kPreferencesFolderType,
  194.                                              kCreateFolder,
  195.                          &foundVRefNum,
  196.                                              &foundDirID);
  197.                                              
  198.         if (myErr==noErr)
  199.             {
  200.  
  201.                 *theRefNum = HOpenResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs", fsWrPerm);
  202.                 myErr = ResError();
  203.                 
  204.                 if (myErr==fnfErr)
  205.                     {
  206.                         HCreateResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs");
  207.                         myErr = ResError();
  208.  
  209.                         *theRefNum = HOpenResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs", fsWrPerm);
  210.                         myErr = ResError();
  211.                     }
  212.             }
  213.         return(myErr);
  214.     }
  215.     
  216. pascal OSErr ClosePrefsResFile(short theRefNum)
  217.     {
  218.         CloseResFile(theRefNum);
  219.         return(ResError());
  220.     }
  221.  
  222. /*
  223.     Name : AddMenuScript
  224.     Purpose : Adds a compiled script OSAID into the
  225.               global menuScripts array for later access
  226. */
  227. pascal void AddMenuScript(short thisID, OSAID thisScriptID)
  228.     {
  229.         if (gNumScripts<kMaxScriptsInApp)
  230.             {
  231.                 menuScripts[gNumScripts].theResID    = thisID;
  232.                 menuScripts[gNumScripts].theScriptID = thisScriptID;
  233.                 gNumScripts ++;
  234.             }
  235.     }
  236.  
  237. /*
  238.     Name : BuildMenuScripts
  239.     Purpose : Reads compiled scripts from the prefs file,
  240.               Any uncompiled scripts ('SCPT' resources with
  241.                         no 'Scpt' of same id are compiled, and a compiled
  242.                         version stored in the prefs file. Any which fail
  243.                         to compile are ignored.
  244. */
  245. pascal void BuildMenuScripts(void)
  246.     {
  247.         short   numScripts;
  248.         short   index;
  249.         short   thisID;
  250.         ResType thisType;
  251.         Handle  myScript;
  252.         AEDesc  myLoadScriptDesc;
  253.         AEDesc  myStoreScriptDesc;
  254.         OSAID   myLoadID;
  255.         OSErr   myErr;
  256.         OSErr   ignoreErr;
  257.         Str255  resName;
  258.         
  259.         GetOpenPreferencesResourceFile(&gPrefsRefFile);
  260.         
  261.         gNumScripts = 0;
  262.         
  263.         menuScripts = (MyScriptRecord *)NewPtr(sizeof(MyScriptRecord)*kMaxScriptsInApp);
  264.         
  265.         numScripts  = Count1Resources(kCompiledScriptType);
  266.         for (index=0; index <numScripts; index++)
  267.             {
  268.                 myScript  = Get1IndResource(kCompiledScriptType, index+1);
  269.                 GetResInfo(myScript, &thisID, &thisType, resName);
  270.                 
  271.               HLock(myScript);
  272.                 
  273.                 myErr = AECreateDesc(typeOSAGenericStorage,
  274.                                                          (Ptr)*myScript,
  275.                                                          GetHandleSize(myScript),
  276.                                                          &myLoadScriptDesc);
  277.                 
  278.                 HUnlock(myScript);
  279.                 
  280.                 if (myErr==noErr)
  281.                     {
  282.                         myLoadID = 0; // Added for Gustav a8
  283.                         
  284.                         myErr = OSALoad(gScriptingComponent,
  285.                                                         &myLoadScriptDesc,
  286.                                                         0,
  287.                                                         &myLoadID);
  288.                                                         
  289.                       if (myErr==noErr)
  290.                             AddMenuScript(thisID,myLoadID);
  291.                     }
  292.                 
  293.                 ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  294.             }
  295.             
  296.         numScripts  = CountResources(kTextScriptType);
  297.         for (index=0; index <numScripts; index++)
  298.             {
  299.                 myScript  = GetIndResource(kTextScriptType, index+1);
  300.                 GetResInfo(myScript, &thisID, &thisType, resName);
  301.                 
  302.                 if (GetScriptIDForResID(thisID)==kOSANullScript)
  303.                     {
  304.                         HLock(myScript);
  305.                         
  306.                         myErr = AECreateDesc(typeChar,
  307.                                                                  (Ptr)*myScript,
  308.                                                                  GetHandleSize(myScript),
  309.                                                                  &myLoadScriptDesc);
  310.                         
  311.                         HUnlock(myScript);
  312.                         
  313.                         if (myErr==noErr)
  314.                             {
  315.                                 myLoadID = 0; // Added for alpha 8
  316.                                 
  317.                                 myErr = OSACompile(gScriptingComponent,
  318.                                                                      &myLoadScriptDesc,
  319.                                                                      0,
  320.                                                                      &myLoadID);
  321.                                                                 
  322.                                 if (myErr==noErr)
  323.                                     AddMenuScript(thisID,myLoadID);
  324.                                     
  325.                                 if (myErr==noErr)
  326.                                     {
  327.                                         myErr = OSAStore(gScriptingComponent,
  328.                                                                          myLoadID,
  329.                                                                          typeOSAGenericStorage,
  330.                                                                          0,
  331.                                                                          &myStoreScriptDesc);
  332.                                                                          
  333.                                         if (myErr==noErr)
  334.                                             {
  335.                                                 myScript = myStoreScriptDesc.dataHandle;
  336.                                                 
  337.                                                 HandToHand(&myScript);                                 
  338.                                                 AddResource(myScript, kCompiledScriptType, thisID, (unsigned char *)"\pMenu Script");
  339.                                             }
  340.                                         
  341.                                         myErr = AEDisposeDesc(&myStoreScriptDesc);
  342.                                     }
  343.                                     
  344.                             }
  345.                         
  346.                         ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  347.                     }
  348.             }
  349.     }
  350.     
  351. /*
  352.     Name:   InitEditorScripting
  353.     Purpose:Connects to the AppleScript component.
  354.             If not currently running it searches all volumes
  355.                     with a desktop database, and launches it if found.
  356.                     It then tries for approx. 1 min to connect to the
  357.                     newly launched AppleScript component.
  358. */
  359. pascal OSErr InitEditorScripting(void)
  360.     {
  361.       OSErr                myErr;
  362.         ComponentDescription descr;
  363.         ComponentDescription capabilities;
  364.         Component            myComponent;
  365.         EventRecord          myEvent;
  366.         short                retryCount;
  367.         
  368.         SetCursor(&waitCursor);
  369.         
  370.         // Out of date stuff - now it's an extension!
  371.         // myErr = EnsureGustavIsLaunched();
  372.         // if (myErr)
  373.         //     return(myErr);
  374.             
  375.         retryCount = 0;
  376.         
  377.         do {
  378.           
  379.             /* Don't lose the high level events - expect a null back */
  380.             
  381.           myErr = WaitNextEvent(mDownMask+mUpMask+keyDownMask+keyUpMask+autoKeyMask,
  382.                                   &myEvent,
  383.                                                         240, /* 4 seconds */
  384.                                                         nil);
  385.         
  386.             descr.componentType         = kOSAComponentType;
  387.             descr.componentSubType      = kAppleScriptSubtype;
  388.             descr.componentManufacturer = (OSType) 0;
  389.             descr.componentFlags        = kOSASupportsCompiling + 
  390.                                           kOSASupportsGetSource + 
  391.                                                                         kOSASupportsAESending;
  392.                                                                         
  393.             descr.componentFlagsMask    = descr.componentFlags;
  394.             
  395.             myComponent = FindNextComponent(nil, &descr);
  396.             
  397.             retryCount++;
  398.             
  399.         } while (myComponent==nil && retryCount<15); /* Try for one minute */
  400.         
  401.         if (myComponent==nil)
  402.           return(kComponentNotFound);
  403.         else
  404.           {
  405.                 myErr = GetComponentInfo(myComponent,
  406.                                                                  &capabilities,
  407.                                                                  nil,
  408.                                                                  nil,
  409.                                                                  nil);
  410.                                                                  
  411.               gScriptingComponent = OpenComponent(myComponent);
  412.                                                                                                     
  413.                 if (gScriptingComponent==nil)
  414.                     return(kComponentNotFound);
  415.             }
  416.             
  417.         myErr = OSAGetSendProc(gScriptingComponent,
  418.                                                      &oldSendProc,
  419.                                                      &refCon);
  420.                                                 
  421.         myErr = OSASetSendProc(gScriptingComponent,
  422.                                                      NewOSASendProc(MySendProc),
  423.                                                      0);
  424.         
  425.         menuScripts = nil;
  426.         
  427.         BuildMenuScripts();
  428.                 
  429.         SetCursor(&qd.arrow);
  430.                     
  431.         return(myErr);
  432.     }
  433.     
  434. /*
  435.     Name    : CloseEditorScripting
  436.     Purpose : Shutdown of editor scripting capabilities
  437. */
  438. pascal OSErr CloseEditorScripting(void)
  439.     {
  440.       OSErr myErr;
  441.         short ctr;
  442.         
  443.         ClosePrefsResFile(gPrefsRefFile);
  444.         
  445.         for (ctr=0; ctr<gNumScripts; ctr++)
  446.             myErr = OSADispose(gScriptingComponent, menuScripts[ctr].theScriptID);
  447.         
  448.         myErr = CloseComponent(gScriptingComponent);
  449.         
  450.         return(myErr);
  451.     }
  452.     
  453. /*
  454.     Name:    DisplayErrorInScript
  455.     Purpose: Put up an alert showing the error text for the last error.
  456.              Also selects the responsible text in theHTE if one is supplied
  457. */
  458.  
  459. pascal void DisplayErrorInScript(TEHandle theHTE)
  460.     {
  461.         Str255   errorMessageText;
  462.         AEDesc   errRangeDesc;
  463.         AEDesc   errRecordDesc;
  464.         AEDesc   errTextDesc;
  465.         AEDesc   errNumberDesc;
  466.         DescType typeCode;
  467.         Size     actSize;
  468.         OSErr    myErr;
  469.         OSErr    ignoreErr;
  470.         OSErr    errorNumber;
  471.         short    errorStart;
  472.         short    errorEnd;
  473.         
  474.         SetCursor(&qd.arrow);
  475.         
  476.         myErr = OSAScriptError(gScriptingComponent,
  477.                                                      kOSAErrorNumber,
  478.                                                      typeShortInteger,
  479.                                                      &errNumberDesc);
  480.         
  481.         myErr = GetIntegerFromDescriptor(&errNumberDesc, &errorNumber);
  482.                 
  483.         ignoreErr = AEDisposeDesc(&errNumberDesc);
  484.         
  485.         myErr = OSAScriptError(gScriptingComponent,
  486.                                                      kOSAErrorMessage,
  487.                                                      typeChar,
  488.                                                      &errTextDesc);
  489.                                                      
  490.         myErr = GetPStringFromDescriptor(&errTextDesc, (char *)errorMessageText);
  491.         
  492.         ignoreErr = AEDisposeDesc(&errTextDesc);
  493.         
  494.         if (theHTE)
  495.             {
  496.                 myErr = OSAScriptError(gScriptingComponent,
  497.                                                              kOSAErrorRange,
  498.                                                              typeOSAErrorRange,
  499.                                                              &errRangeDesc);
  500.                                                              
  501.                 myErr = AECoerceDesc(&errRangeDesc, typeAERecord, &errRecordDesc);
  502.                 
  503.                 ignoreErr = AEDisposeDesc(&errRangeDesc);
  504.                 
  505.                 myErr = AEGetKeyPtr(&errRecordDesc,
  506.                                     keyOSASourceStart,
  507.                                                         typeShortInteger,
  508.                                                         &typeCode,
  509.                                                         (Ptr)&errorStart,
  510.                                                         sizeof(errorStart),
  511.                                                         &actSize);
  512.                                                         
  513.                 myErr = AEGetKeyPtr(&errRecordDesc,
  514.                                     keyOSASourceEnd,
  515.                                                         typeShortInteger,
  516.                                                         &typeCode,
  517.                                                         (Ptr)&errorEnd,
  518.                                                         sizeof(errorEnd),
  519.                                                         &actSize);
  520.                                                         
  521.                 ignoreErr = AEDisposeDesc(&errRecordDesc);
  522.                 
  523.                 TESetSelect(errorStart, errorEnd, theHTE);
  524.             }
  525.         
  526.         ShowError(errorMessageText, errorNumber);
  527.     }
  528. /*
  529.     Name    : CompileDocument
  530.     Purpose : Compiles the text of the supplied document - does NOT keep
  531.               a compiled version - merely checks that it will compile for now
  532. */
  533. pascal OSErr CompileDocument(DPtr theDoc)
  534.     {
  535.         OSErr             myErr;
  536.         OSErr             ignoreErr;
  537.         TEHandle          theHTE;
  538.         AEDesc            windowTextDesc;
  539.         AEDesc            myCompiledText;
  540.         AEDesc            styledTextDesc;
  541.         AEDesc            textStyleDesc;
  542.         AEDesc            rawTextDesc;
  543.         OSAID             myScriptID;
  544.         
  545.         /*
  546.           Initialise handles
  547.         */
  548.         
  549.         myCompiledText.dataHandle = nil;
  550.         windowTextDesc.dataHandle = nil;
  551.         
  552.         theHTE = theDoc->theText;
  553.         
  554.         HLock((Handle)(**theHTE).hText);
  555.         myErr = AECreateDesc(typeChar,
  556.                                                  (Ptr)&(*(**theHTE).hText)[0],
  557.                                                  (**theHTE).teLength,
  558.                                                  &windowTextDesc);
  559.                                                  
  560.         HUnlock((Handle)(**theHTE).hText);
  561.         
  562.         if (myErr==noErr)
  563.             {
  564.                 myScriptID = 0; // Added for Gustav 1.0a8
  565.                 
  566.                 myErr = OSACompile(gScriptingComponent,
  567.                                    &windowTextDesc,
  568.                                                      0,
  569.                                                      &myScriptID);
  570.                 
  571.                 if (myErr==noErr)
  572.                   {
  573.                         myErr = OSAGetSource(gScriptingComponent,
  574.                                                                  myScriptID,
  575.                                                                  typeStyledText,
  576.                                                                  &myCompiledText);
  577.                         if (myErr==noErr)
  578.                             {
  579.                                 styledTextDesc.dataHandle = nil;
  580.                                 textStyleDesc.dataHandle  = nil;
  581.                                 rawTextDesc.dataHandle    = nil;
  582.                             
  583.                               /*
  584.                                     Coerce to an AERecord and then extract the parts of the
  585.                                     styled text
  586.                                 */
  587.                                 myErr = AECoerceDesc(&myCompiledText, typeAERecord, &styledTextDesc);
  588.                                 
  589.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  590.                                                      keyAEText,
  591.                                                                          typeChar,
  592.                                                                          &rawTextDesc);
  593.                                                                          
  594.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  595.                                                      keyAEStyles,
  596.                                                                          typeScrapStyles,
  597.                                                                          &textStyleDesc);
  598.                                                                          
  599.                                 TESetSelect(0,32000, theHTE);
  600.                                 TEDelete(theHTE);
  601.                                 
  602.                                 HLock((Handle)rawTextDesc.dataHandle);
  603.                                                                          
  604.                                 TEStylInsert((const void *) (*rawTextDesc.dataHandle),
  605.                                              GetHandleSize(rawTextDesc.dataHandle),
  606.                                                          (StScrpHandle) textStyleDesc.dataHandle,
  607.                                                          theHTE);
  608.                                                          
  609.                                 HUnlock((Handle)rawTextDesc.dataHandle);
  610.                                 
  611.                                 if (textStyleDesc.dataHandle)
  612.                                     ignoreErr = AEDisposeDesc(&textStyleDesc);
  613.                         
  614.                                 if (rawTextDesc.dataHandle)
  615.                                     ignoreErr = AEDisposeDesc(&rawTextDesc);
  616.  
  617.                                 if (styledTextDesc.dataHandle)
  618.                                     ignoreErr = AEDisposeDesc(&styledTextDesc);
  619.  
  620.                             }
  621.                         
  622.                     }
  623.                 else
  624.                     DisplayErrorInScript(theHTE);
  625.                     
  626.                 if (myErr==noErr)
  627.                   ignoreErr = OSADispose(gScriptingComponent,
  628.                                            myScriptID);
  629.             }
  630.             
  631.         if (myCompiledText.dataHandle)
  632.             ignoreErr = AEDisposeDesc(&myCompiledText);
  633.             
  634.         if (windowTextDesc.dataHandle)
  635.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  636.  
  637.         return(myErr);
  638.         
  639.     }
  640.     
  641. /*
  642.     Name    : ExecuteDocument
  643.     Purpose : Compiles the text of the supplied document and then executes it
  644.               - does NOT keep a compiled version after execution
  645. */
  646. pascal OSErr ExecuteDocument(DPtr theDoc)
  647.   {
  648.         OSErr             myErr;
  649.         OSErr             ignoreErr;
  650.         TEHandle          theHTE;
  651.         AEDesc            windowTextDesc;
  652.         AEDesc            myCompiledText;
  653.         OSAID             myScriptID;
  654.         OSAID             myExecutedScriptID;
  655.         
  656.         /*
  657.           Initialise handles
  658.         */
  659.         
  660.         myCompiledText.dataHandle = nil;
  661.         windowTextDesc.dataHandle = nil;
  662.         
  663.         theHTE = theDoc->theText;
  664.         
  665.         HLock((Handle)(**theHTE).hText);
  666.         myErr = AECreateDesc(typeChar,
  667.                                                  (Ptr)&(*(**theHTE).hText)[0],
  668.                                                  (**theHTE).teLength,
  669.                                                  &windowTextDesc);
  670.                                                  
  671.         HUnlock((Handle)(**theHTE).hText);
  672.         
  673.         if (myErr==noErr)
  674.             {
  675.                 myScriptID = 0; // Added for Gustav 1.0a8
  676.                 
  677.                 myErr = OSACompile(gScriptingComponent,
  678.                                    &windowTextDesc,
  679.                                                      0,
  680.                                                      &myScriptID);
  681.                                                      
  682.                 if (myErr==noErr)
  683.                   {
  684.                         myErr = OSAExecute(gScriptingComponent,
  685.                                            myScriptID,
  686.                                                              kOSANullScript,
  687.                                                              0,
  688.                                                              &myExecutedScriptID);
  689.                 
  690.                       if (myErr!=noErr)
  691.                           DisplayErrorInScript(theHTE);
  692.                             
  693.                         myErr = OSAGetSource(gScriptingComponent,
  694.                                                                  myScriptID,
  695.                                                                  typeStyledText,
  696.                                                                  &myCompiledText);
  697.                         if (myErr==noErr)
  698.                             {
  699.                                 /* Zap current contents and
  700.                                      replace with returned source */
  701.                                                                  
  702.                                 TESetSelect(0, 32000, theHTE);
  703.                                 TEDelete(theHTE);
  704.  
  705.                                 myErr = GetStyledTextFromDescIntoTEHandle(&myCompiledText, theHTE);
  706.                                     
  707.                                 if (myErr==noErr)
  708.                                     ignoreErr = OSADispose(gScriptingComponent,
  709.                                                                                  myExecutedScriptID);
  710.                             }
  711.                         
  712.                     }
  713.                 else
  714.                     DisplayErrorInScript(theHTE);
  715.                     
  716.                 if (myErr==noErr)
  717.                   ignoreErr = OSADispose(gScriptingComponent,
  718.                                            myScriptID);
  719.             }
  720.             
  721.         if (myCompiledText.dataHandle)
  722.             ignoreErr = AEDisposeDesc(&myCompiledText);
  723.             
  724.         if (windowTextDesc.dataHandle)
  725.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  726.  
  727.         return(myErr);        
  728.     }
  729.  
  730. /* 
  731.     Name   : ScriptForMenuExists
  732.     Purpose: Tests for the existance of a valid script for a given menu item             
  733. */
  734.     
  735. pascal OSErr ScriptForMenuExists(short theMenu, short theItem, Boolean *exists)
  736.     {
  737.         short  resID;
  738.         OSAID  myScriptID;
  739.         OSErr  myErr;
  740.         
  741.         myErr = noErr;
  742.         
  743.         resID = (theMenu<<5) + theItem;
  744.         
  745.         myScriptID = GetScriptIDForResID(resID);
  746.         
  747.         if (myScriptID==kOSANullScript)
  748.             if (theItem!=0)
  749.                 myErr = ScriptForMenuExists(theMenu, 0, exists);
  750.             else
  751.                 *exists = false;
  752.         else
  753.           *exists = true;
  754.                 
  755.         return(myErr);        
  756.     } /* ScriptForMenuExists */
  757.     
  758.     
  759. /* 
  760.     Name   : ExecuteScriptForMenu
  761.     Purpose: Executes a script associated with the menu item.
  762.              Should be called only after ScriptForMenuExists
  763.                      returns exists.
  764. */    
  765. pascal OSErr ExecuteScriptForMenu(short theMenu, short theItem)
  766.   {
  767.         short  resID;
  768.         OSAID  myScriptID;
  769.         OSAID  myExecuteID;
  770.         OSErr  myErr;
  771.         OSErr  ignoreErr;
  772.                 
  773.         resID = (theMenu<<5) + theItem;
  774.         
  775.         myScriptID = GetScriptIDForResID(resID);
  776.                 
  777.         if (myScriptID==kOSANullScript)
  778.           {
  779.                 resID = (theMenu<<5); /* look for a script for the whole menu - item 0 */
  780.                 myScriptID = GetScriptIDForResID(resID);
  781.             }
  782.         
  783.         if (myScriptID != kOSANullScript)
  784.           {
  785.                 gActiveMenuItem = theItem;
  786.                 
  787.                 myErr = OSAExecute(gScriptingComponent,
  788.                                                      myScriptID,
  789.                                                      kOSANullScript,
  790.                                                      0,
  791.                                                      &myExecuteID);
  792.                                                      
  793.                 ignoreErr = OSADispose(gScriptingComponent,
  794.                                        myExecuteID);
  795.                 
  796.                 gActiveMenuItem = 0;
  797.             }
  798.  
  799.         return(myErr);
  800.     }
  801.  
  802. /*
  803.     Name :   GetScriptActiveItem
  804.     Purpose : Used by SVAppleEvents for the active item property of a menu.
  805.               Allows a script associated with more than one menu item to
  806.                         find which menu item it was called by.
  807. */
  808. pascal short GetScriptActiveItem(void)
  809.     {
  810.         return(gActiveMenuItem);
  811.     }
  812.     
  813. /*
  814.     Routines used in the StyledTextEdit Dialog Item
  815. */
  816.  
  817. struct StyleTextInfo {
  818.     ControlHandle theScrollBar;
  819.     TEHandle      theTEHandle;
  820. };
  821.  
  822. typedef struct StyleTextInfo StyleTextInfo;
  823.  
  824. typedef StyleTextInfo *pStyleTextInfo;
  825.  
  826. pascal void DrawStyledTextEditRec(DialogPtr theDialog, short theItem)
  827.     {
  828.         short   theType;
  829.         Handle  theHandle;
  830.         Rect    itemRect;
  831.                 
  832.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  833.         FrameRect(&itemRect);
  834.         InsetRect(&itemRect, 5, 5);
  835.         
  836.         TEUpdate(&itemRect, ((pStyleTextInfo) GetWRefCon(theDialog))->theTEHandle);
  837.     }
  838.     
  839. pascal void DrawScrollBar(DialogPtr theDialog, short theItem)
  840.     {        
  841. #pragma unused(theItem)
  842.  
  843.         Draw1Control(((pStyleTextInfo) GetWRefCon(theDialog))->theScrollBar);
  844.     }
  845.  
  846. /*
  847.     Name:    SetDrawProcForUserItem
  848.     Purpose: Installs a procedure that will be called when theItem needs
  849.              to be drawn.
  850. */
  851. pascal void SetDrawProcForUserItem(DialogPtr theDialog, short theItem, ProcPtr theProc)
  852.     {
  853.         short  theType;
  854.         Handle theHandle;
  855.         Rect   itemRect;
  856.         
  857.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  858.         SetDItem(theDialog, theItem, theType, (Handle)theProc, &itemRect);
  859.     }
  860.     
  861. /*
  862.     Name:    FlashButton
  863.     Purpose: Provide visual effect of button having been
  864.              selected.
  865. */
  866.  
  867. pascal void FlashButton(DialogPtr theDialog, short theItem)
  868.     {
  869.         short    theType;
  870.         Handle   theHandle;
  871.         Rect     itemRect;
  872.         
  873.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  874.         
  875.         HiliteControl((ControlHandle)theHandle, inButton);
  876.         HiliteControl((ControlHandle)theHandle, 0);
  877.     }
  878.     
  879. /* 
  880.     Name:    ScrollVActionProc
  881.     Purpose: Called as scrollbar is tracked in buttons or page up/down.
  882.              Keeps text in sync with scrollBar
  883. */
  884. pascal void ScrollVActionProc(ControlHandle control, short part)
  885.   {
  886.         short  amount;
  887.         short  initialValue;
  888.         
  889.     if (part)
  890.       {
  891.                 switch (part) {
  892.                   case inUpButton:
  893.                     case inDownButton : amount = 24;
  894.                                         break;
  895.                   case inPageUp:
  896.                     case inPageDown   : amount = (**control).contrlRect.bottom - 
  897.                                                  (**control).contrlRect.top;
  898.                                         break;
  899.                                                             
  900.                 }   /* case */
  901.                 
  902.                 if (part == inUpButton || part == inPageUp)
  903.           amount = -amount; /* reverse direction */
  904.             
  905.                 initialValue = GetCtlValue(control);
  906.  
  907.               SetCtlValue(control, initialValue+amount); /* Pinned within Min/Max automatically */
  908.                 
  909.                 amount  = GetCtlValue(control)-initialValue;                
  910.                 
  911.                 if (amount)
  912.           TEScroll(0, -amount, ((pStyleTextInfo)GetWRefCon((**control).contrlOwner))->theTEHandle);
  913.  
  914.             }     /* if */
  915.     }  /* ScrollVActionProc */
  916.     
  917. /*
  918.     Name:    TrackTEPosn
  919.     Purpose: Ensures that the scrollbar value matches the position
  920.              of the text edit record.
  921. */
  922. pascal void TrackTEPosn(ControlHandle theControl, TEHandle theHTE)
  923.     {
  924.         short shouldBe;
  925.         
  926.       shouldBe = (**theHTE).viewRect.top - 
  927.                                 (**theHTE).destRect.top;
  928.                                 
  929.         if (GetCtlValue(theControl)!=shouldBe)
  930.             SetCtlValue(theControl,shouldBe);
  931.     }
  932.  
  933. /*
  934.     Name:    SetScrollLimit
  935.     Purpose: Ensures that the maximum value of the scrollbar is sufficient
  936.              to allow showing of all text, and no more.
  937. */
  938. pascal void SetScrollLimit(ControlHandle newScroll, TEHandle theHTE)
  939.     {
  940.         Point     teLimit;
  941.         short     currentMax;
  942.         short     currentValue;
  943.         TextStyle theStyle;
  944.         short     lineHeight;
  945.         short     fontAscent;
  946.         
  947.         currentMax = GetCtlMax(newScroll);
  948.         
  949.         /*
  950.             Scroll max should be position of bottom of bottom line when unscrolled
  951.             This is equal to
  952.               The position of the bottom line relative to current position +
  953.                 The amount currently scrolled -
  954.                 The height of the visible part
  955.         */
  956.                 
  957.         teLimit    = TEGetPoint((**theHTE).teLength, theHTE); // Position of bottom relative to current posn
  958.         
  959.         TEGetStyle((**theHTE).teLength, &theStyle, &lineHeight, &fontAscent,theHTE);        
  960.         teLimit.v += lineHeight-fontAscent; // Add in for descent - TEGetPoint is posn of baseline not bottom of chars
  961.         
  962.         teLimit.v    += ((**theHTE).viewRect.top -(**theHTE).destRect.top); // Amount already scrolled
  963.         
  964.         teLimit.v -= ((**theHTE).viewRect.bottom - (**theHTE).viewRect.top); // Height of page
  965.         
  966.         if (teLimit.v<0) // Cannot be negative
  967.             teLimit.v = 0;
  968.             
  969.         if (currentMax>teLimit.v)
  970.             {
  971.                 currentValue = GetCtlValue(newScroll);
  972.                 if (currentValue>teLimit.v)
  973.                     {
  974.                         TEScroll(0, teLimit.v - currentValue, theHTE);
  975.                         SetCtlValue(newScroll, teLimit.v);
  976.                     }
  977.                 SetCtlMax(newScroll, teLimit.v);
  978.             }
  979.             
  980.         if (currentMax<teLimit.v)
  981.             SetCtlMax(newScroll, teLimit.v);
  982.     }
  983.  
  984. #define kCompile   3
  985. #define kTextItem  4
  986. #define kScrollBar 5
  987.  
  988. pascal Boolean MyFilterProc(DialogPtr theDialog, EventRecord *myEvent, short *itemHit)
  989.     {
  990.       short         myPart;
  991.         WindowPtr     whichWindow;
  992.         TEHandle      newTE;
  993.         Boolean       extend;
  994.         GrafPtr       oldPort;
  995.         Point         mousePt;
  996.         char          myKey;
  997.         Boolean       returnVal;
  998.         long          menuResult;
  999.         Rect          teItemRect;
  1000.         Rect          scrollItemRect;
  1001.         ControlHandle newScroll;
  1002.         ControlHandle theControl;
  1003.         short         part;
  1004.         short         value;
  1005.         short         cntlCode;
  1006.         
  1007.         GetPort(&oldPort);
  1008.         
  1009.         returnVal = false;
  1010.         
  1011.         newTE     = ((pStyleTextInfo)GetWRefCon(theDialog))->theTEHandle;
  1012.         newScroll = ((pStyleTextInfo)GetWRefCon(theDialog))->theScrollBar;
  1013.         
  1014.         TEIdle(newTE);
  1015.         
  1016.         /* Maintain the cursor */
  1017.         
  1018.         SetPort(theDialog);
  1019.         GetMouse(&mousePt);
  1020.         
  1021.         GetRectOfDialogItem(theDialog, kTextItem,  &teItemRect);
  1022.         GetRectOfDialogItem(theDialog, kScrollBar, &scrollItemRect);
  1023.         
  1024.         if (PtInRect(mousePt, &teItemRect))
  1025.             SetCursor(&editCursor);
  1026.         else
  1027.             SetCursor(&qd.arrow);
  1028.             
  1029.         switch (myEvent->what) {
  1030.             case mouseDown: myPart = FindWindow(myEvent->where, &whichWindow);
  1031.                                             if (whichWindow==theDialog)
  1032.                                                 switch (myPart) {
  1033.                                                     case inContent:
  1034.                                                     case inGrow:        SetPort(whichWindow);
  1035.                                                                                     mousePt = myEvent->where;
  1036.                                                                                     GlobalToLocal(&mousePt);
  1037.  
  1038.                                                                                     extend = ((myEvent->modifiers & shiftKey) != 0);
  1039.                                                                                     if (PtInRect(mousePt, &(*(newTE))->viewRect))
  1040.                                                                                         {
  1041.                                                                                             TEClick(mousePt, extend, newTE);
  1042.                                                                                             TrackTEPosn(newScroll, newTE);
  1043.                                                                                         }
  1044.  
  1045.                                                                                     if (PtInRect(mousePt, &scrollItemRect))
  1046.                                                                                          {
  1047.                                                                                                  cntlCode = FindControl(mousePt, theDialog, &theControl);
  1048.                                                                                                 if (theControl)
  1049.                                                                                                     if (cntlCode == inThumb)
  1050.                                                                                                         {
  1051.                                                                                                             value = GetCtlValue(theControl);
  1052.                                                                                                             part  = TrackControl(theControl,
  1053.                                                                                                                                                      mousePt,
  1054.                                                                                                                                                      nil);
  1055.                                                                                                             if (part)
  1056.                                                                                                                 {
  1057.                                                                                                                     value -= GetCtlValue(theControl);
  1058.                                                                                                                     if (value)
  1059.                                                                                                                         TEScroll(0, value, newTE);
  1060.                                                                                                                 } /* if */
  1061.                                                                                                         }
  1062.                                                                                                     else
  1063.                                                                                                       if (cntlCode!=0)
  1064.                                                                                                           part = TrackControl(theControl, mousePt, (ControlActionUPP)ScrollVActionProc);
  1065.                                                                                             }
  1066.                                                                                     break;
  1067.                                                         
  1068.                                                     case inDrag:      DragWindow(whichWindow,
  1069.                                                                                                          myEvent->where,
  1070.                                                                                                          &qd.screenBits.bounds);
  1071.                                                                                     returnVal = true; /* Stops modal dialog beeping */
  1072.                                                                                     break;
  1073.                                                     
  1074.                                                     case inMenuBar: /* Allows turn on/off of ballon help */
  1075.                                                                                     menuResult = MenuSelect(myEvent->where);
  1076.                                                                                     break;                                                                                        
  1077.                                                     }
  1078.                                             break;
  1079.             case keyDown:
  1080.             case autoKey: /* Need hooks here for command keys if menus enabled */
  1081.                                         myKey = myEvent->message & charCodeMask;
  1082.                                         if (myKey==3)
  1083.                                             {
  1084.                                                 *itemHit = kCompile;
  1085.                                                 FlashButton(theDialog, kCompile);
  1086.                                                 returnVal = true;
  1087.                                             }
  1088.                                         else
  1089.                                             {
  1090.                                                 TEKey(myKey, newTE);
  1091.                                                 SetScrollLimit(newScroll, newTE);
  1092.                                                 TrackTEPosn(newScroll, newTE);
  1093.                                             }
  1094.                                         break;
  1095.                                         
  1096.             case activateEvt: if (((myEvent->modifiers & activeFlag) != 0))
  1097.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1098.                                                         TEActivate(newTE);
  1099.                                                     else
  1100.                                                         DoActivate((WindowPtr)myEvent->message, true); /* Should not get here! */
  1101.                                                 else
  1102.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1103.                                                         TEDeactivate(newTE);
  1104.                                                     else
  1105.                                                         DoActivate((WindowPtr)myEvent->message, false);
  1106.                                                         
  1107.                                                 break;
  1108.                                                 
  1109.             case updateEvt  : if (Ours((WindowPtr)myEvent->message))
  1110.                                                     DoUpdate(DPtrFromWindowPtr((WindowPtr)myEvent->message));
  1111.                                                 break;
  1112.         }
  1113.         
  1114.         SetPort(oldPort);
  1115.         
  1116.         return(returnVal);
  1117.     }
  1118.  
  1119. pascal OSErr EditMenuScript(short theMenu, short theItem)
  1120.  {
  1121.         short         resID;
  1122.         OSAID         myScriptID;
  1123.         OSErr         myErr;
  1124.         OSErr         ignoreErr;
  1125.         AEDesc        scriptTextDesc;
  1126.         DialogPtr     scriptEditDlog;
  1127.         short         itemHit;
  1128.         TEHandle      newTE;
  1129.         GrafPtr       oldPort;
  1130.         Rect          itemRect;
  1131.         OSAID         myCompiledID;
  1132.         Handle        myScript;
  1133.         Boolean       wholeMenu;
  1134.         ControlHandle myScrollBar;
  1135.         StyleTextInfo theStyleTextInfo;
  1136.         ModalFilterUPP modalFilterDescriptor;
  1137.         
  1138.         GetPort(&oldPort);
  1139.         
  1140.         /*
  1141.             Look for a script associated with theItem first,
  1142.             and if not found look for one associated with 
  1143.             the whole menu
  1144.         */
  1145.         
  1146.         wholeMenu = false;
  1147.         
  1148.         resID = (theMenu<<5) + theItem;
  1149.         
  1150.         myScriptID = GetScriptIDForResID(resID);
  1151.         
  1152.         if (myScriptID==kOSANullScript)
  1153.           {
  1154.                 resID = (theMenu<<5);
  1155.                 myScriptID = GetScriptIDForResID(resID);
  1156.                 wholeMenu = true;
  1157.             }
  1158.                 
  1159.         scriptEditDlog = GetNewDialog(400, nil, (WindowPtr)-1);                     
  1160.         SetPort(scriptEditDlog);
  1161.         /*
  1162.             Create a styled text edit record for the userItem
  1163.             and install it
  1164.         */
  1165.         GetRectOfDialogItem(scriptEditDlog, kTextItem,  &itemRect);
  1166.         
  1167.         InsetRect(&itemRect, 5, 5);
  1168.         
  1169.         newTE = TEStylNew(&itemRect, &itemRect);
  1170.         
  1171.         TEAutoView(true, newTE);
  1172.         
  1173.         SetDrawProcForUserItem(scriptEditDlog, kTextItem,(ProcPtr)DrawStyledTextEditRec);
  1174.         
  1175.         /*
  1176.             Now create a scrollbar and install it
  1177.         */
  1178.         
  1179.         GetRectOfDialogItem(scriptEditDlog, kScrollBar, &itemRect);
  1180.         
  1181.         myScrollBar = NewControl(scriptEditDlog,
  1182.                                  &itemRect,
  1183.                                                          (unsigned char *)"",
  1184.                                                          true,
  1185.                                                          0,
  1186.                                                          0,
  1187.                                                          32000, // Will be fixed up later - by SetScrollLimit()
  1188.                                                          scrollBarProc,
  1189.                                                          0);
  1190.                                                          
  1191.         SetDrawProcForUserItem(scriptEditDlog, kScrollBar,(ProcPtr)DrawScrollBar);
  1192.         
  1193.         /*
  1194.             Use the dialog window refcon to allow access to the 
  1195.             TEHandle and scrollHandle avoiding the use
  1196.             of globals
  1197.         */
  1198.         
  1199.         theStyleTextInfo.theTEHandle  = newTE;
  1200.         theStyleTextInfo.theScrollBar = myScrollBar;
  1201.         
  1202.         SetWRefCon(scriptEditDlog, (long) &theStyleTextInfo);
  1203.  
  1204.         /*
  1205.             Put the source of the script into the 
  1206.             text edit record
  1207.         */
  1208.         
  1209.         myErr = OSAGetSource(gScriptingComponent,
  1210.                                                  myScriptID,
  1211.                                                  typeStyledText,
  1212.                                                  &scriptTextDesc);
  1213.       GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1214.         
  1215.         ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1216.         
  1217.         SetScrollLimit(myScrollBar, newTE);
  1218.         TrackTEPosn(myScrollBar, newTE);
  1219.         
  1220.         /*    Added during PowerPC port: */
  1221.         
  1222.         modalFilterDescriptor = NewModalFilterProc(MyFilterProc);
  1223.         
  1224.         do {
  1225.             ModalDialog(modalFilterDescriptor, &itemHit);
  1226.             switch (itemHit){
  1227.                 case ok        :
  1228.                 case kCompile  :  SetCursor(&waitCursor);
  1229.                                                     HLock((Handle)(**newTE).hText);
  1230.                                   myErr = AECreateDesc(typeChar,
  1231.                                                                                             (Ptr)*((**newTE).hText),
  1232.                                                                                             (**newTE).teLength,
  1233.                                                                                             &scriptTextDesc);
  1234.                                                                                             
  1235.                                                   HUnlock((Handle)(**newTE).hText);
  1236.                                                     
  1237.                                                     myCompiledID = 0; // Added for Gustav 1.0a8
  1238.                                                     myErr = OSACompile(gScriptingComponent,
  1239.                                                                                          &scriptTextDesc,
  1240.                                                                                          0,
  1241.                                                                                          &myCompiledID);
  1242.                                                                                          
  1243.                                                     ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1244.                                                     
  1245.                                                     scriptTextDesc.dataHandle = nil;
  1246.                                                     
  1247.                                                   if (myErr==noErr)
  1248.                                                       {
  1249.                                                             myErr = OSAGetSource(gScriptingComponent,
  1250.                                                                                                      myCompiledID,
  1251.                                                                                                      typeStyledText,
  1252.                                                                                                      &scriptTextDesc);
  1253.                                                                                                      
  1254.                                                             /* Zap current contents and
  1255.                                                                replace with returned source */
  1256.                                                                  
  1257.                                                             TESetSelect(0, 32000, newTE);
  1258.                                                             TEDelete(newTE);
  1259.                                                             SetCtlValue(myScrollBar, 0); // We deleted all the text so it won't be scrolled anymore
  1260.                                                             
  1261.                                                             GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1262.                                                             
  1263.                                                             DrawStyledTextEditRec(scriptEditDlog, kTextItem);
  1264.                                                                                                  
  1265.                                                             ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1266.                                                         }
  1267.                                                     else
  1268.                                                         {
  1269.                                                             DisplayErrorInScript(newTE);
  1270.                                                             itemHit  = 0; // Stop dialog going away
  1271.                                                         }
  1272.                                                         
  1273.                                                     SetScrollLimit(myScrollBar, newTE);
  1274.                                                     TrackTEPosn(myScrollBar, newTE);
  1275.                                                 
  1276.                                                     SetCursor(&qd.arrow);
  1277.                                                         
  1278.                                                     if (itemHit==ok)
  1279.                                                         if (myErr==noErr)
  1280.                                                             {
  1281.                                                                 // Swap this script for the old one unless whole menu 
  1282.                                                               
  1283.                                                                 if (wholeMenu)
  1284.                                                                     myScriptID = kOSANullScript;
  1285.                                                                     
  1286.                                                                 myErr = OSACopyID(gScriptingComponent,
  1287.                                                                                                      myCompiledID,
  1288.                                                                                                      &myScriptID);
  1289.                                                                                                      
  1290.                                                                 myErr = OSAStore(gScriptingComponent,
  1291.                                                                                                  myScriptID,
  1292.                                                                                                  typeOSAGenericStorage,
  1293.                                                                                                  0,
  1294.                                                                                                  &scriptTextDesc);
  1295.                                                                                                  
  1296.                                                                 if (myErr==noErr)
  1297.                                                                     {
  1298.                                                                         /* should prompt for whole menu if mod 32 == 0 */
  1299.                                                                       
  1300.                                                                         resID = (theMenu<<5) + theItem;
  1301.                                                                         
  1302.                                                                         /* Remove it if it's already in the prefs file */
  1303.                                                                         
  1304.                                                                         myScript = Get1Resource(kCompiledScriptType, resID);
  1305.                                                                         
  1306.                                                                         if (myScript!=nil && ResError()==noErr)
  1307.                                                                             RmveResource(myScript);
  1308.                                                                         
  1309.                                                                         /* And create a new resource */
  1310.                                                                         
  1311.                                                                         myScript = scriptTextDesc.dataHandle;
  1312.                                                                         
  1313.                                                                         HLock((Handle)myScript);
  1314.                                                                         HandToHand(&myScript);                                 
  1315.                                                                         AddResource(myScript, kCompiledScriptType, resID, (unsigned char *)"\pMenu Script");
  1316.                                                                         UpdateResFile(CurResFile());
  1317.                                                                         HUnlock((Handle)myScript);
  1318.                                                                         
  1319.                                                                         if (wholeMenu)
  1320.                                                                           AddMenuScript(resID, myScriptID);
  1321.                                                                     }
  1322.                                                                 myErr = AEDisposeDesc(&scriptTextDesc);
  1323.                                                             }
  1324.                                                         else
  1325.                                                             itemHit = -1;
  1326.                                                             
  1327.                                                     ignoreErr = OSADispose(gScriptingComponent,
  1328.                                                                                                  myCompiledID);
  1329.                                                     
  1330.                 case cancel    : 
  1331.                 case kTextItem : 
  1332.                 case kScrollBar: break;
  1333.             }
  1334.     } while (itemHit!=ok && itemHit!=cancel);
  1335.                 
  1336.         DisposeRoutineDescriptor(modalFilterDescriptor);
  1337.                 
  1338.         DisposeDialog(scriptEditDlog);
  1339.         
  1340.         SetPort(oldPort);
  1341.         
  1342.         return(noErr);
  1343.  }